package com.uzai.console.service.mini.impl;

import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.uzai.common.exception.BusinessException;
import com.uzai.common.result.ResponseCode;
import com.uzai.console.common.utils.DateUtil;
import com.uzai.console.common.utils.UrlUtils;
import com.uzai.console.config.UzaiConsoleSysConfig;
import com.uzai.console.dto.BaseDto;
import com.uzai.console.dto.mini.deviceminiinfo.*;
import com.uzai.console.dto.wxpubmanage.WxpubInfoListQuery;
import com.uzai.console.entity.DeviceMiniInfo;
import com.uzai.console.entity.MiniCode;
import com.uzai.console.entity.MiniComponentAuth;
import com.uzai.console.entity.wxpubmanage.WxpubInfoEntity;
import com.uzai.console.jsonvo.mini.AccountBasicInfo;
import com.uzai.console.jsonvo.mini.AuthorizationInfo;
import com.uzai.console.jsonvo.mini.MiniBaseResult;
import com.uzai.console.jsonvo.mini.RegisterMiniprogramByOffiaccount;
import com.uzai.console.mapper.DeviceMiniInfoMapper;
import com.uzai.console.mapper.MiniCodeMapper;
import com.uzai.console.mapper.MiniComponentAuthMapper;
import com.uzai.console.mapper.WxpubInfoMapper;
import com.uzai.console.service.mini.DeviceMiniInfoService;
import com.uzai.console.service.mini.MiniOptService;
import com.uzai.console.vo.mini.deviceminiinfo.ComponentAuthVo;
import com.uzai.console.vo.mini.deviceminiinfo.DeviceMiniInfoVo;
import com.uzai.console.vo.mini.deviceminiinfo.FastRegisterAuthVo;
import com.uzai.console.vo.mini.deviceminiinfo.WxpubSelectKeyVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author liuqi
 * @date 2021年08月23日 20:25
 */
@Service
public class DeviceMiniInfoServiceImpl implements DeviceMiniInfoService {

    private Logger logger = LoggerFactory.getLogger(DeviceMiniInfoServiceImpl.class);

    @Autowired
    private DeviceMiniInfoMapper deviceMiniInfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WxpubInfoMapper wxpubInfoMapper;
    @Autowired
    private MiniOptService miniOptService;
    @Autowired
    private UzaiConsoleSysConfig uzaiConsoleSysConfig;
    @Autowired
    private MiniComponentAuthMapper miniComponentAuthMapper;
    @Autowired
    private MiniCodeMapper miniCodeMapper;

    /**
     * 分页查询小程序授权列表
     * @author liuqi
     * @date 2021/8/13 11:38
     * @return DeviceMiniInfoVo
     */
    public Page<DeviceMiniInfoVo> findDeviceMiniInfoByPage(DeviceMiniInfoQuery deviceMiniInfoQuery){
        //新建返回到页面的LIST对象
        List<DeviceMiniInfoVo> deviceMiniInfoVoList = new ArrayList<>();
        //返回到页面分页对象
        Page<DeviceMiniInfoVo> pageVo = new Page<>();

        //执行分页查询对象
        Page<DeviceMiniInfo> page = new Page<>();
        deviceMiniInfoQuery.convert(page);
        List<DeviceMiniInfo> deviceMiniInfoList = deviceMiniInfoMapper.findByList(page, deviceMiniInfoQuery);

        if(deviceMiniInfoList != null && deviceMiniInfoList.size() > 0){

            //查询系统最新版本号
            MiniCode miniCode = miniCodeMapper.selectNewestAndUpload(8888L);
            if(miniCode == null){
                miniCode = new MiniCode();
            }

            for (DeviceMiniInfo deviceMiniInfo : deviceMiniInfoList){
                DeviceMiniInfoVo deviceMiniInfoVo = new DeviceMiniInfoVo();
                BeanUtils.copyProperties(deviceMiniInfo, deviceMiniInfoVo);
                //设置系统最新版本号
                deviceMiniInfoVo.setCodeVersionNewest(miniCode.getVersion());
                deviceMiniInfoVoList.add(deviceMiniInfoVo);
            }
        }

        BeanUtils.copyProperties(page, pageVo);
        pageVo.setRecords(deviceMiniInfoVoList);
        //将分页信息复制到返回到页面的分页MO当中
        return pageVo;
    }

    /**
     * 查询小程序授权详情
     * @author liuqi
     * @date 2021/8/13 11:38
     * @return DeviceMiniInfoVo
     */
    public DeviceMiniInfoVo findDeviceMiniInfoById(DeviceMiniInfoIdDto deviceMiniInfoIdDto){

        //返回的对象
        DeviceMiniInfoVo deviceMiniInfoVo = new DeviceMiniInfoVo();

        if(deviceMiniInfoIdDto.getId() == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入id");
        }

        DeviceMiniInfo deviceMiniInfo = deviceMiniInfoMapper.selectById(deviceMiniInfoIdDto.getId(), deviceMiniInfoIdDto.getMerId());
        if(deviceMiniInfo == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "该记录不存在");
        }

        //查询系统最新版本号
        MiniCode miniCode = miniCodeMapper.selectNewestAndUpload(8888L);
        if(miniCode == null){
            miniCode = new MiniCode();
        }

        BeanUtils.copyProperties(deviceMiniInfo, deviceMiniInfoVo);

        //设置系统最新版本号
        deviceMiniInfoVo.setCodeVersionNewest(miniCode.getVersion());

        return deviceMiniInfoVo;
    }

    /**
     * 复用公众号快速创建小程序授权url
     * @author liuqi
     * @date 2021/8/13 11:38
     * @return CmsTbGoodsInfoVo
     */
   public FastRegisterAuthVo fastregisterCreateUrl(FastregisterCreateUrlDto fastregisterCreateUrlDto){
       FastRegisterAuthVo fastRegisterAuthVo = new FastRegisterAuthVo();

       if(fastregisterCreateUrlDto.getAppid() == null){
           throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入公众号apppid");
       }

       WxpubInfoEntity wxpubInfoEntity = wxpubInfoMapper.queryObjectByAppId(fastregisterCreateUrlDto.getAppid());
       if(wxpubInfoEntity == null){
           throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "公众号不存在");
       }

       //第三方平台appid
       String componentAppid = uzaiConsoleSysConfig.getMiniComponentAppid();
       //回调函数
       String redirectUri = uzaiConsoleSysConfig.getMiniFastRegisterRedirectUri();
       //替换自定义参数
       String status = fastregisterCreateUrlDto.getMerId() + "_" + fastregisterCreateUrlDto.getAppid();
       redirectUri = String.format(redirectUri, status);

       String authUrl = miniOptService.createFastregisterAuthUrl(fastregisterCreateUrlDto.getAppid(), componentAppid, UrlUtils.encode(redirectUri), "1");

       //链接需urlencode
       String authUrl_encode = URLEncoder.encode(authUrl);

       //封装微信小程序url发起页(微信要求发起页域名和正式域名保存一样)
       String miniInitPage = uzaiConsoleSysConfig.getMiniInitPage();
       //从发起页中请求url
       fastRegisterAuthVo.setAuthUrl(miniInitPage + authUrl_encode);
       return fastRegisterAuthVo;
   }

    /**
     * 复用公众号快速创建小程序授权回调之后创建小程序
     * @author liuqi
     * @param status 自定义参数:merId_appid
     * @date 2021/8/13 11:38
     * @return CmsTbGoodsInfoVo
     */
    @Transactional
    public void fastregisterCallback(String status, String ticket){
        if(status == null || ticket == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "参数错误");
        }

        String[] statusList = status.split("_");
        if(statusList == null || statusList.length < 2){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "自定义参数错误");
        }

        Long merId = Long.valueOf(statusList[0]); //第一位为运营商id
        String appid = String.valueOf(statusList[1]); //第二位为复用公众号appid

        WxpubInfoEntity wxpubInfoEntity = wxpubInfoMapper.queryObjectByAppId(appid);
        if(wxpubInfoEntity == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "公众号不存在");
        }

        //查询该授权令牌
        String authorizerAccessToken = null;
        String authorizerAccessToken_key = String.format("auth_access_token_%s", wxpubInfoEntity.getWxAppId());
        Object object = redisTemplate.opsForValue().get(authorizerAccessToken_key);
        if(object != null){
            authorizerAccessToken = object.toString();
        }
        if(StringUtils.isBlank(authorizerAccessToken)){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "未找到该公众号授权");
        }

        int now = DateUtil.getNowTime();

        RegisterMiniprogramByOffiaccount miniprogramByOffiaccount =  miniOptService.registerMiniprogramByOffiaccount(authorizerAccessToken, ticket);
        logger.info("--复用公众号快速创建小程序-result={}", JSONObject.toJSONString(miniprogramByOffiaccount));

        //创建小程序-同时保存该小程序授权信息
        if(miniprogramByOffiaccount != null && miniprogramByOffiaccount.is_wx_verify_succ()){
            //授权码
            String authorization_code = miniprogramByOffiaccount.getAuthorization_code();
            //获取第三方平台令牌
            String miniComponentAppid = uzaiConsoleSysConfig.getMiniComponentAppid();
            String componentAccessToken = miniOptService.getComponentAccessToken(miniComponentAppid, uzaiConsoleSysConfig.getMiniComponentAppsecret(), null);
            //获取小程序授权信息
            AuthorizationInfo authorizationInfo = miniOptService.getAuthorizationInfo(componentAccessToken, miniComponentAppid, authorization_code);
            if(authorizationInfo == null){
                logger.error("--获取小程序授权信息失败-");
                throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "获取授权信息失败");
            }

            //获取小程序基本信息
            AccountBasicInfo accountBasicInfo = miniOptService.getAccountBasicInfo(authorizationInfo.getAuthorizer_access_token());
            if(accountBasicInfo == null){
                logger.error("--获取小程序基本信息信息失败-");
                throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "获取小程序基本信息信息失败");
            }

            //添加小程序授权令牌
            MiniComponentAuth miniComponentAuth_mini = new MiniComponentAuth();
            miniComponentAuth_mini.setId(IdWorker.getId());
            miniComponentAuth_mini.setComponentAppid(miniComponentAppid);
            miniComponentAuth_mini.setAuthorizerAppid(accountBasicInfo.getAppid());
            miniComponentAuth_mini.setAuthorizerAccessToken(authorizationInfo.getAuthorizer_access_token());
            miniComponentAuth_mini.setAuthorizerRefreshToken(authorizationInfo.getAuthorizer_refresh_token());
            miniComponentAuth_mini.setAuthTime(DateUtil.getNowTime());
            miniComponentAuth_mini.setExpiresIn(authorizationInfo.getExpires_in());
            miniComponentAuth_mini.setCreateTime(now);
            miniComponentAuth_mini.setUpdateTime(now);
            miniComponentAuthMapper.insert(miniComponentAuth_mini);

            //创建复用小程序，先查询是否存在
            DeviceMiniInfo deviceMiniInfo = deviceMiniInfoMapper.selectByAppId(accountBasicInfo.getAppid());
            if(deviceMiniInfo != null){
                logger.error("--此小程序已有运营商使用-appid={},merid={}",accountBasicInfo.getAppid(), deviceMiniInfo.getMerId());
                throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "此小程序已有运营商使用");
            }else{
                deviceMiniInfo = new DeviceMiniInfo();
                deviceMiniInfo.setId(IdWorker.getId());
                deviceMiniInfo.setMerId(wxpubInfoEntity.getMerId());
                deviceMiniInfo.setMiniAppId(accountBasicInfo.getAppid());
                deviceMiniInfo.setMiniAppSecret(null);
                deviceMiniInfo.setMiniOriginalId(accountBasicInfo.getAppid());
                deviceMiniInfo.setDeviceId(accountBasicInfo.getAppid());
                deviceMiniInfo.setDeviceName(accountBasicInfo.getNickname());
                deviceMiniInfo.setDeviceRemark(null);
                deviceMiniInfo.setConfigId(null);
                deviceMiniInfo.setHeadImgUrl(accountBasicInfo.getHead_image_info().getHead_image_url());
                deviceMiniInfo.setAuthStatus(1);//已授权
                deviceMiniInfo.setRedirectUrl(null);
                deviceMiniInfo.setPayName(null);
                deviceMiniInfo.setPayAppId(null);
                deviceMiniInfo.setZfAppKey(null);
                deviceMiniInfo.setZfAppId(null);
                deviceMiniInfo.setPayAchNo(null);
                deviceMiniInfo.setPaySecret(null);
                deviceMiniInfo.setPayApiclientCert(null);
                deviceMiniInfo.setPayApiclientKey(null);
                deviceMiniInfo.setPayRemark(null);
                deviceMiniInfo.setAuthStatus(1);//已授权
                deviceMiniInfo.setAuthType(0); //授权类型(0-复用公众号快速注册;1-已有小程序授权)
                deviceMiniInfo.setCreateTime(now);
                deviceMiniInfo.setUpdateTime(now);
                deviceMiniInfoMapper.insert(deviceMiniInfo);

                //获取最新版的已经提交的代码(运营商为8888L默认官方god)
                MiniCode miniCode_new = miniCodeMapper.selectNewestAndUpload(8888L);
                //上传代码并生成体验版接口
                if(miniCode_new != null){
                    //上传代码接口参数ext_json
                    JSONObject ext_json = new JSONObject();
                    List<String> requiredPrivateInfos = new ArrayList<>();
                    requiredPrivateInfos.add("chooseAddress");
                    ext_json.put("requiredPrivateInfos", requiredPrivateInfos); //默认
                    ext_json.put("extEnable", true);
                    MiniBaseResult miniBaseResult = miniOptService.commitCode(miniComponentAuth_mini.getAuthorizerAccessToken(), miniCode_new.getTemplateId(), JSONObject.toJSONString(ext_json), miniCode_new.getVersion(), miniCode_new.getDesc());
                    if (miniBaseResult != null && miniBaseResult.getErrcode() == 0) {//成功
                        MiniCode miniCode_appId = new MiniCode();
                        miniCode_appId.setId(IdWorker.getId());
                        miniCode_appId.setMerId(deviceMiniInfo.getMerId());
                        miniCode_appId.setMiniAppId(deviceMiniInfo.getMiniAppId());
                        miniCode_appId.setTemplateId(miniCode_new.getTemplateId());
                        miniCode_appId.setName(miniCode_new.getName());
                        miniCode_appId.setVersion(miniCode_new.getVersion());
                        miniCode_appId.setDesc(miniCode_new.getDesc());
                        miniCode_appId.setMsg(miniCode_new.getMsg());
                        miniCode_appId.setRemark(miniCode_new.getRemark());
                        miniCode_appId.setUpload(1); //已上传代码
                        miniCode_appId.setStatus(0); //未审核
                        miniCode_appId.setCreateTime(now);
                        miniCode_appId.setUpdateTime(now);
                        miniCodeMapper.insert(miniCode_appId);
                    }
                }
            }
        }
    }

    /**
     * 查询复用公众号列表
     * @author liuqi
     * @date 2021/8/13 11:38
     * @return CmsTbGoodsInfoVo
     */
    public List<WxpubSelectKeyVo> findWxpubList(BaseDto baseDto){
        List<WxpubSelectKeyVo> wxpubSelectKeyVoList = new ArrayList<>();

        WxpubInfoListQuery wxpubInfoListQuery = new WxpubInfoListQuery();
        wxpubInfoListQuery.setMerId(baseDto.getMerId());
        List<WxpubInfoEntity> wxpubInfoEntityList = wxpubInfoMapper.queryList(wxpubInfoListQuery);

        if(wxpubInfoEntityList != null && wxpubInfoEntityList.size() > 0){
            for (WxpubInfoEntity wxpubInfoEntity : wxpubInfoEntityList){
                WxpubSelectKeyVo wxpubSelectKeyVo = new WxpubSelectKeyVo();
                wxpubSelectKeyVo.setId(wxpubInfoEntity.getId());
                wxpubSelectKeyVo.setWxpubAppId(wxpubInfoEntity.getWxAppId());
                wxpubSelectKeyVo.setWxpubName(wxpubInfoEntity.getDeviceName());
                //查询该公众号是否已经授权,从缓存中获取
                String authorizerAccessToken_key = String.format("auth_access_token_%s", wxpubInfoEntity.getWxAppId());
                Object object = redisTemplate.opsForValue().get(authorizerAccessToken_key);
                if(object != null){
                    wxpubSelectKeyVo.setAuthFlag(1); //已经授权
                }
            }
        }

        return wxpubSelectKeyVoList;
    }

    /**
     * 小程序授权创建url信息
     * @author liuqi
     * @date 2021/8/13 11:38
     * @return CmsTbGoodsInfoVo
     */
    public ComponentAuthVo authCreateUrl(AuthCreateUrlDto componentAuthDto){
        ComponentAuthVo componentAuthVo = new ComponentAuthVo();

        //第三方平台appid
        String component_appid = uzaiConsoleSysConfig.getMiniComponentAppid();
        if(StringUtils.isBlank(component_appid)){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "第三方平台appid为空");
        }

        //第三方平台密钥
        String componentAppsecret = uzaiConsoleSysConfig.getMiniComponentAppsecret();
        if(StringUtils.isBlank(componentAppsecret)){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "第三方平台appsecret为空");
        }

        //第三方平台令牌
        String component_access_token = miniOptService.getComponentAccessToken(component_appid, componentAppsecret, null);
        if(StringUtils.isBlank(component_access_token)){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "未获取第三方平台令牌");
        }

        //获取预授权码
        String preAuthCode = miniOptService.getPreAuthCode(component_appid, component_access_token);
        if(StringUtils.isBlank(preAuthCode)){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "未获取到第三方平台预授权码");
        }

        //授权回调函数
        String redirectUri = uzaiConsoleSysConfig.getMiniAuthRedirectUri();
        //替换自定义参数
        String status = componentAuthDto.getMerId() + "_" + componentAuthDto.getAuthtype();
        redirectUri = String.format(redirectUri, status);

        //创建小程序授权链接
        String authUrl = miniOptService.createAuthUrlPc(component_appid, preAuthCode, UrlUtils.encode(redirectUri), componentAuthDto.getAuthtype(), null, null);

        //链接需urlencode
        String authUrl_encode = URLEncoder.encode(authUrl);

        //封装微信小程序url发起页(微信要求发起页域名和正式域名保存一样)
        String miniInitPage = uzaiConsoleSysConfig.getMiniInitPage();
        //从发起页中请求url
        componentAuthVo.setAuthUrl(miniInitPage + authUrl_encode);

        return componentAuthVo;
    }

    /**
     * 小程序授权回调函数
     * @author liuqi
     * @param status 自定义参数:merId_authtype（1-公众号；2-小程序）
     * @date 2021/8/13 11:38
     * @return CmsTbGoodsInfoVo
     */
    public void authCallback(String status, String auth_code, Integer expires_in){
        if(StringUtils.isBlank(status) || StringUtils.isBlank(auth_code) || expires_in == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "参数错误");
        }

        String[] statusList = status.split("_");
        if(statusList == null || statusList.length < 2){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "自定义参数错误");
        }

        Long merId = Long.valueOf(statusList[0]); //第一位为运营商id
        Integer authtype = Integer.valueOf(statusList[1]); //第二位为授权类型

        int now = DateUtil.getNowTime();

        //获取第三方平台令牌
        String miniComponentAppid = uzaiConsoleSysConfig.getMiniComponentAppid();
        String componentAccessToken = miniOptService.getComponentAccessToken(miniComponentAppid, uzaiConsoleSysConfig.getMiniComponentAppsecret(), null);
        //获取小程序授权信息
        AuthorizationInfo authorizationInfo = miniOptService.getAuthorizationInfo(componentAccessToken, miniComponentAppid, auth_code);
        if(authorizationInfo == null){
            logger.error("--获取授权信息失败-");
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "获取授权信息失败");
        }

        //获取小程序基本信息
        AccountBasicInfo accountBasicInfo = miniOptService.getAccountBasicInfo(authorizationInfo.getAuthorizer_access_token());
        if(accountBasicInfo == null){
            logger.error("--获取基本信息信息失败-");
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "获取基本信息信息失败");
        }

        //小程序授权
        if(authtype.intValue() == 2){
            //更新授权表
            MiniComponentAuth miniComponentAuth = miniComponentAuthMapper.selectByAuthorizerAppid(accountBasicInfo.getAppid());
            if(miniComponentAuth != null){//存在则修改
                miniComponentAuth.setAuthTime(DateUtil.getNowTime());
                miniComponentAuth.setAuthorizerAccessToken(authorizationInfo.getAuthorizer_access_token());
                miniComponentAuth.setAuthorizerRefreshToken(authorizationInfo.getAuthorizer_refresh_token());
                miniComponentAuth.setExpiresIn(authorizationInfo.getExpires_in());
                miniComponentAuthMapper.updateById(miniComponentAuth);
            }else{ //不存在则添加
                miniComponentAuth = new MiniComponentAuth();
                miniComponentAuth.setId(IdWorker.getId());
                miniComponentAuth.setComponentAppid(miniComponentAppid);
                miniComponentAuth.setAuthorizerAppid(accountBasicInfo.getAppid());
                miniComponentAuth.setAuthorizerAccessToken(authorizationInfo.getAuthorizer_access_token());
                miniComponentAuth.setAuthorizerRefreshToken(authorizationInfo.getAuthorizer_refresh_token());
                miniComponentAuth.setAuthTime(DateUtil.getNowTime());
                miniComponentAuth.setExpiresIn(authorizationInfo.getExpires_in());
                miniComponentAuth.setCreateTime(now);
                miniComponentAuth.setUpdateTime(now);
                miniComponentAuthMapper.insert(miniComponentAuth);
            }

            DeviceMiniInfo deviceMiniInfo = deviceMiniInfoMapper.selectByAppId(accountBasicInfo.getAppid());
            if(deviceMiniInfo != null){ //修改
                //如果数据库存在的小程序
                if(deviceMiniInfo.getMerId().longValue() != merId){
                    logger.error("--此小程序已有运营商使用-appid={},merid={}",accountBasicInfo.getAppid(), deviceMiniInfo.getMerId());
                    throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "此小程序已有运营商使用");
                }
                deviceMiniInfo.setId(IdWorker.getId());
                deviceMiniInfo.setMiniAppId(accountBasicInfo.getAppid());
                deviceMiniInfo.setMiniAppSecret(null);
                deviceMiniInfo.setMiniOriginalId(accountBasicInfo.getAppid());
                deviceMiniInfo.setDeviceId(accountBasicInfo.getAppid());
                deviceMiniInfo.setDeviceName(accountBasicInfo.getNickname());
                deviceMiniInfo.setHeadImgUrl(accountBasicInfo.getHead_image_info().getHead_image_url());
                deviceMiniInfo.setAuthStatus(1);//已授权
                deviceMiniInfo.setAuthType(1); //已有小程序注册
                deviceMiniInfoMapper.updateByIdSelective(deviceMiniInfo);
            }else{//添加
                //小程序信息
                deviceMiniInfo = new DeviceMiniInfo();
                deviceMiniInfo.setId(IdWorker.getId());
                deviceMiniInfo.setMerId(merId);
                deviceMiniInfo.setMiniAppId(accountBasicInfo.getAppid());
                deviceMiniInfo.setMiniAppSecret(null);
                deviceMiniInfo.setMiniOriginalId(accountBasicInfo.getAppid());
                deviceMiniInfo.setDeviceId(accountBasicInfo.getAppid());
                deviceMiniInfo.setDeviceName(accountBasicInfo.getNickname());
                deviceMiniInfo.setDeviceRemark(null);
                deviceMiniInfo.setConfigId(null);
                deviceMiniInfo.setHeadImgUrl(accountBasicInfo.getHead_image_info().getHead_image_url());
                deviceMiniInfo.setAuthStatus(1);//已授权
                deviceMiniInfo.setRedirectUrl(null);
                deviceMiniInfo.setPayName(null);
                deviceMiniInfo.setPayAppId(null);
                deviceMiniInfo.setZfAppKey(null);
                deviceMiniInfo.setZfAppId(null);
                deviceMiniInfo.setPayAchNo(null);
                deviceMiniInfo.setPaySecret(null);
                deviceMiniInfo.setPayApiclientCert(null);
                deviceMiniInfo.setPayApiclientKey(null);
                deviceMiniInfo.setPayRemark(null);
                deviceMiniInfo.setCreateTime(now);
                deviceMiniInfo.setUpdateTime(now);
                deviceMiniInfo.setAuthStatus(1);//已授权
                deviceMiniInfo.setAuthType(1); //已有小程序注册
                deviceMiniInfoMapper.insert(deviceMiniInfo);

                //获取最新版的已经提交的代码(运营商为8888L默认官方god)
                MiniCode miniCode_new = miniCodeMapper.selectNewestAndUpload(8888L);
                //上传代码并生成体验版接口
                if(miniCode_new != null){
                    //上传代码接口参数ext_json
                    JSONObject ext_json = new JSONObject();
                    List<String> requiredPrivateInfos = new ArrayList<>();
                    requiredPrivateInfos.add("chooseAddress");
                    ext_json.put("requiredPrivateInfos", requiredPrivateInfos); //默认
                    ext_json.put("extEnable", true);
                    MiniBaseResult miniBaseResult = miniOptService.commitCode(miniComponentAuth.getAuthorizerAccessToken(), miniCode_new.getTemplateId(), JSONObject.toJSONString(ext_json), miniCode_new.getVersion(), miniCode_new.getDesc());
                    if (miniBaseResult != null && miniBaseResult.getErrcode() == 0) {//成功
                        MiniCode miniCode_appId = new MiniCode();
                        miniCode_appId.setId(IdWorker.getId());
                        miniCode_appId.setMerId(deviceMiniInfo.getMerId());
                        miniCode_appId.setMiniAppId(deviceMiniInfo.getMiniAppId());
                        miniCode_appId.setTemplateId(miniCode_new.getTemplateId());
                        miniCode_appId.setName(miniCode_new.getName());
                        miniCode_appId.setVersion(miniCode_new.getVersion());
                        miniCode_appId.setDesc(miniCode_new.getDesc());
                        miniCode_appId.setMsg(miniCode_new.getMsg());
                        miniCode_appId.setRemark(miniCode_new.getRemark());
                        miniCode_appId.setUpload(1); //已上传代码
                        miniCode_appId.setStatus(0); //未审核
                        miniCode_appId.setCreateTime(now);
                        miniCode_appId.setUpdateTime(now);
                        miniCodeMapper.insert(miniCode_appId);
                    }
                }
            }
        }else if(authtype.intValue() == 1){//公众号授权为了兼容旧版公众号授权，故刷新缓存就行，因为旧版公众号就是存放缓存当中
            String accessKey = String.format("auth_access_token_%s", authorizationInfo.getAuthorizer_appid());
            String refreshKey = String.format("auth_refresh_token_%s",authorizationInfo.getAuthorizer_appid());
            redisTemplate.opsForValue().set(accessKey, authorizationInfo.getAuthorizer_access_token(), 7100L, TimeUnit.SECONDS);
            redisTemplate.opsForValue().set(refreshKey, authorizationInfo.getAuthorizer_refresh_token(), 7100L, TimeUnit.SECONDS);
        }
    }

    /**
     * 小程序授权设置支付信息
     * @author liuqi
     * @date 2021/8/13 11:38
     * @return CmsTbGoodsInfoVo
     */
    public void setPayinfo(SetPayInfoDto setPayInfoDto){

        if(setPayInfoDto.getId() == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入小程序主键id");
        }

        if(StringUtils.isBlank(setPayInfoDto.getZfAppId())){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入账房appid");
        }

        if(StringUtils.isBlank(setPayInfoDto.getZfAppKey())){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入账房appkey");
        }

        DeviceMiniInfo deviceMiniInfo = deviceMiniInfoMapper.selectById(setPayInfoDto.getId(), setPayInfoDto.getMerId());
        if(deviceMiniInfo == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "该小程序不存在");
        }

        //修改账房支付信息
        deviceMiniInfo.setZfAppId(setPayInfoDto.getZfAppId());
        deviceMiniInfo.setZfAppKey(setPayInfoDto.getZfAppKey());
        deviceMiniInfo.setUpdateTime(DateUtil.getNowTime());
        deviceMiniInfoMapper.updatePayInfoById(deviceMiniInfo);
    }

    /**
     * 获取不限制的小程序码
     *
     * @return null
     * @author liuqi
     * @date 2021/8/13 11:38
     */
    public String getUnlimitedQRCode(DeviceMiniInfoIdDto deviceMiniInfoIdDto){
        if(deviceMiniInfoIdDto.getId() == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入主键id");
        }

        DeviceMiniInfo deviceMiniInfo = deviceMiniInfoMapper.selectById(deviceMiniInfoIdDto.getId(), deviceMiniInfoIdDto.getMerId());
        if(deviceMiniInfo == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "该小程序不存在");
        }

        //获取授权令牌
        MiniComponentAuth miniComponentAuth = miniComponentAuthMapper.selectByAuthorizerAppid(deviceMiniInfo.getMiniAppId());
        //授权
        if (miniComponentAuth == null) {
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "未找到该小程序的授权令牌");
        }

        int now = DateUtil.getNowTime();
        if (miniComponentAuth.getExpiresIn() + miniComponentAuth.getAuthTime() < now) {
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "该小程序的授权令牌已经到期");
        }

        //获取不限制的小程序码
        byte[] data = miniOptService.getUnlimitedQRCode(miniComponentAuth.getAuthorizerAccessToken(), null);
        String encodeStr = Base64.encode(data);
        encodeStr = "data:image/jpeg;base64," + encodeStr;
        return encodeStr;
    }

    /**
     * 小程序授权设置订阅消息
     * @author liuqi
     * @date 2021/8/13 11:38
     * @return CmsTbGoodsInfoVo
     */
    public void setMsgTemplate(SetMsgTemplateDto setMsgTemplateDto){
        if(setMsgTemplateDto.getId() == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入小程序主键id");
        }

        DeviceMiniInfo deviceMiniInfo = deviceMiniInfoMapper.selectById(setMsgTemplateDto.getId(), setMsgTemplateDto.getMerId());
        if(deviceMiniInfo == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "该小程序不存在");
        }

        //修改账房支付信息
        deviceMiniInfo.setMsgTemplate(JSONObject.toJSONString(setMsgTemplateDto.getMsgTemplate()));
        deviceMiniInfo.setUpdateTime(DateUtil.getNowTime());
        deviceMiniInfoMapper.updateMsgTemplateById(deviceMiniInfo);
    }

    /**
     * 获取小程序基本信息
     * @author liuqi
     * @date 2021/8/13 11:38
     * @return CmsTbGoodsInfoVo
     */
    public AccountBasicInfo getAccountBasicInfo(DeviceMiniInfoIdDto deviceMiniInfoIdDto){
        if(deviceMiniInfoIdDto.getId() == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入小程序主键id");
        }

        DeviceMiniInfo deviceMiniInfo = deviceMiniInfoMapper.selectById(deviceMiniInfoIdDto.getId(), deviceMiniInfoIdDto.getMerId());
        if(deviceMiniInfo == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "该小程序不存在");
        }

        //获取授权令牌
        MiniComponentAuth miniComponentAuth = miniComponentAuthMapper.selectByAuthorizerAppid(deviceMiniInfo.getMiniAppId());
        //授权
        if (miniComponentAuth == null) {
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "未找到该小程序的授权令牌");
        }

        //获取到小程序信息
        AccountBasicInfo accountBasicInfo = miniOptService.getAccountBasicInfo(miniComponentAuth.getAuthorizerAccessToken());
        return accountBasicInfo;

    }

    /**
     * 删除小程序授权
     *
     * @return null
     * @author liuqi
     * @date 2021/8/13 11:38
     */
    @Transactional
    public void deleteDeviceMiniInfo(DeviceMiniInfoIdDto deviceMiniInfoIdDto){
        if(deviceMiniInfoIdDto.getId() == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入小程序主键id");
        }

        DeviceMiniInfo deviceMiniInfo = deviceMiniInfoMapper.selectById(deviceMiniInfoIdDto.getId(), deviceMiniInfoIdDto.getMerId());
        if(deviceMiniInfo == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "该小程序不存在");
        }

        //获取授权令牌
        MiniComponentAuth miniComponentAuth = miniComponentAuthMapper.selectByAuthorizerAppid(deviceMiniInfo.getMiniAppId());
        //授权
        if (miniComponentAuth == null) {
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "未找到该小程序的授权令牌");
        }

        //获取到小程序信息
        AccountBasicInfo accountBasicInfo = miniOptService.getAccountBasicInfo(miniComponentAuth.getAuthorizerAccessToken());
        if(accountBasicInfo != null && accountBasicInfo.getErrcode() == 61007){ //已解绑状态
            //删除小程序
            deviceMiniInfoMapper.deleteById(deviceMiniInfo.getId(), deviceMiniInfo.getMerId());

            //删除小程序授权
            miniComponentAuthMapper.deleteByAuthorizerAppid(miniComponentAuth.getAuthorizerAppid());
        }
    }

}
